"""
策略基类

定义策略的基本接口和通用功能
"""

import time
from abc import ABC, abstractmethod
from typing import Dict, List, Any, Optional
from ..core import unified_logger
from ..database.persistence_service import get_persistence_service
from ..core.exceptions import StrategyError, ValidationError, ExchangeAPIError, NetworkError


class BaseStrategy(ABC):
    """策略基类"""
    
    def __init__(self, config: Dict[str, Any], exchange_adapter, 
                 order_manager, account_manager, data_manager):
        """
        初始化策略
        
        Args:
            config: 策略配置
            exchange_adapter: 交易所适配器
            order_manager: 订单管理器
            account_manager: 账户管理器
            data_manager: 数据管理器
        """
        self.config = config
        self.exchange = exchange_adapter
        self.order_manager = order_manager
        self.account_manager = account_manager
        self.data_manager = data_manager
        
        # 策略基本信息
        self.strategy_name = config.get('name', self.__class__.__name__)
        self.symbol = config.get('symbol', '')
        self.exchange_name = config.get('exchange', '')
        self.market_type = config.get('type', 'spot')  # spot/futures
        
        # 策略状态
        self.running = False
        self.paused = False
        self.backtest_mode = False  # 添加回测模式标志
        self.start_time = 0
        self.last_update_time = 0
        
        # 日志器
        self.logger = unified_logger.get_logger(f'strategy_{self.strategy_name}')
        
        # 持久化服务
        self.persistence = get_persistence_service()
        
        # 策略统计
        self.stats = {
            'total_orders': 0,
            'filled_orders': 0,
            'total_profit': 0.0,
            'win_count': 0,
            'loss_count': 0,
            'max_drawdown': 0.0,
            'start_balance': 0.0,
            'current_balance': 0.0
        }
        
        # 验证配置
        self._validate_config()
        
        self.logger.info(f"策略 {self.strategy_name} 初始化完成")
    
    def set_backtest_mode(self, backtest_mode: bool) -> None:
        """设置回测模式"""
        self.backtest_mode = backtest_mode
        if backtest_mode:
            self.logger.info("策略已切换到回测模式")
    
    def set_order_manager(self, order_manager) -> None:
        """设置订单管理器"""
        self.order_manager = order_manager
        self.logger.info("订单管理器已更新")
    
    def set_account_manager(self, account_manager) -> None:
        """设置账户管理器"""
        self.account_manager = account_manager
        self.logger.info("账户管理器已更新")
    
    def set_data_manager(self, data_manager) -> None:
        """设置数据管理器"""
        self.data_manager = data_manager
        self.logger.info("数据管理器已更新")

    def _validate_config(self) -> None:
        """验证策略配置"""
        required_fields = ['symbol', 'exchange']
        
        for field in required_fields:
            if not self.config.get(field):
                raise ValidationError(f"策略配置缺少必需字段: {field}")
        
        # 验证交易对格式
        if '-' not in self.symbol:
            raise ValidationError(f"交易对格式错误: {self.symbol}")
    
    @abstractmethod
    def initialize(self) -> bool:
        """
        策略初始化
        
        Returns:
            是否初始化成功
        """
        pass
    
    @abstractmethod
    def on_tick(self, data: Dict[str, Any]) -> None:
        """
        处理行情数据，生成交易信号
        
        Args:
            data: 行情数据
        """
        pass
    
    @abstractmethod
    def on_order_update(self, order: Dict[str, Any]) -> None:
        """
        处理订单更新
        
        Args:
            order: 订单信息
        """
        pass
    
    def start(self) -> bool:
        """
        启动策略
        
        Returns:
            是否启动成功
        """
        try:
            if self.running:
                self.logger.warning("策略已在运行中")
                return True
            
            # 初始化策略
            if not self.initialize():
                raise StrategyError("策略初始化失败")
            
            # 记录初始余额
            self._record_initial_balance()
            
            # 保存策略启动信息
            self._save_strategy_start_info()
            
            # 设置状态
            self.running = True
            self.paused = False
            self.start_time = int(time.time())
            self.last_update_time = self.start_time
            
            self.logger.info(f"策略 {self.strategy_name} 启动成功")
            return True
            
        except Exception as e:
            self.logger.error(f"策略启动失败: {e}")
            return False
    
    def stop(self) -> bool:
        """
        停止策略
        
        Returns:
            是否停止成功
        """
        try:
            if not self.running:
                self.logger.warning("策略未在运行")
                return True
            
            # 取消所有活跃订单
            self._cancel_all_active_orders()
            
            # 设置状态
            self.running = False
            self.paused = False
            
            # 记录最终统计
            self._update_final_stats()
            
            # 保存策略停止信息
            self._save_strategy_stop_info()
            
            self.logger.info(f"策略 {self.strategy_name} 停止成功")
            return True
            
        except Exception as e:
            self.logger.error(f"策略停止失败: {e}")
            return False
    
    def pause(self) -> bool:
        """
        暂停策略
        
        Returns:
            是否暂停成功
        """
        try:
            if not self.running:
                self.logger.warning("策略未在运行")
                return False
            
            self.paused = True
            self.logger.info(f"策略 {self.strategy_name} 已暂停")
            return True
            
        except Exception as e:
            self.logger.error(f"策略暂停失败: {e}")
            return False
    
    def resume(self) -> bool:
        """
        恢复策略
        
        Returns:
            是否恢复成功
        """
        try:
            if not self.running:
                self.logger.warning("策略未在运行")
                return False
            
            self.paused = False
            self.logger.info(f"策略 {self.strategy_name} 已恢复")
            return True
            
        except Exception as e:
            self.logger.error(f"策略恢复失败: {e}")
            return False
    
    def is_running(self) -> bool:
        """检查策略是否在运行"""
        return self.running and not self.paused
    
    def place_order(self, order_type: str, side: str, amount: float, 
                   price: Optional[float] = None, leverage: int = 1) -> Optional[str]:
        """
        下单
        
        Args:
            order_type: 订单类型 (limit/market)
            side: 买卖方向 (buy/sell)
            amount: 数量
            price: 价格 (限价单必需)
            leverage: 杠杆倍数
            
        Returns:
            订单ID，失败返回None
        """
        try:
            if not self.is_running():
                self.logger.warning("策略未运行，无法下单")
                return None
            
            # 检查余额
            if not self._check_balance(side, amount, price):
                self.logger.warning("余额不足，无法下单")
                return None
            
            # 创建订单
            order = self.order_manager.create_order(
                exchange=self.exchange_name,
                symbol=self.symbol,
                order_type=order_type,
                side=side,
                amount=amount,
                price=price,
                strategy=self.strategy_name,
                leverage=leverage
            )
            
            if order:
                order_id = order['order_id']
                
                # 提交到交易所
                if self.market_type == 'spot':
                    result = self.exchange.spot_place_order(
                        self.symbol, order_type, side, amount, price
                    )
                else:
                    result = self.exchange.futures_place_order(
                        self.symbol, order_type, side, amount, leverage, price
                    )
                
                if result:
                    # 更新订单状态
                    self.order_manager.update_order_status(order_id, 'submitted')
                    self.stats['total_orders'] += 1
                    
                    # 保存订单信息到数据库
                    self._save_order_info(order, result)
                    
                    self.logger.strategy_log(
                        self.strategy_name,
                        f"下单成功: {side} {amount} {self.symbol} @{price or 'market'}"
                    )
                    
                    return order_id
            
            return None
            
        except ExchangeAPIError as e:
            self.logger.error(f"交易所API错误: {e}")
            # 记录失败的订单
            self.stats['failed_orders'] = self.stats.get('failed_orders', 0) + 1
            return None
        except NetworkError as e:
            self.logger.error(f"网络错误: {e}")
            # 网络错误可能是临时的，记录但不停止策略
            self.stats['network_errors'] = self.stats.get('network_errors', 0) + 1
            return None
        except ValidationError as e:
            self.logger.error(f"参数验证错误: {e}")
            return None
        except Exception as e:
            self.logger.error(f"下单失败: {e}")
            # 记录未知错误
            self.stats['unknown_errors'] = self.stats.get('unknown_errors', 0) + 1
            return None
    
    def cancel_order(self, order_id: str) -> bool:
        """
        取消订单
        
        Args:
            order_id: 订单ID
            
        Returns:
            是否取消成功
        """
        try:
            # 从交易所取消订单
            result = self.exchange.cancel_order(order_id, self.symbol)
            
            if result:
                # 更新本地订单状态
                self.order_manager.update_order_status(order_id, 'cancelled')
                
                self.logger.strategy_log(
                    self.strategy_name,
                    f"取消订单成功: {order_id}"
                )
                
                return True
            
            return False
            
        except Exception as e:
            self.logger.error(f"取消订单失败: {e}")
            return False
    
    def get_latest_price(self) -> Optional[float]:
        """
        获取最新价格
        
        Returns:
            最新价格
        """
        try:
            return self.exchange.get_latest_price(self.symbol)
        except Exception as e:
            self.logger.error(f"获取最新价格失败: {e}")
            return None
    
    def get_kline_data(self, period: str, limit: int = 100) -> Optional[List[Dict[str, Any]]]:
        """
        获取K线数据
        
        Args:
            period: 时间周期
            limit: 数据条数
            
        Returns:
            K线数据列表
        """
        try:
            end_time = int(time.time())
            start_time = end_time - self._get_period_seconds(period) * limit
            
            data = self.data_manager.get_kline_data(
                exchange=self.exchange_name,
                market_type=self.market_type,
                symbol=self.symbol,
                period=period,
                start_time=start_time,
                end_time=end_time
            )
            
            if data is not None:
                return data.to_dict('records')
            
            return None
            
        except Exception as e:
            self.logger.error(f"获取K线数据失败: {e}")
            return None
    
    def _get_period_seconds(self, period: str) -> int:
        """获取时间周期对应的秒数"""
        period_map = {
            '1m': 60,
            '5m': 300,
            '15m': 900,
            '30m': 1800,
            '1h': 3600,
            '4h': 14400,
            '1d': 86400
        }
        return period_map.get(period, 60)
    
    def _check_balance(self, side: str, amount: float, price: Optional[float]) -> bool:
        """检查余额是否充足"""
        try:
            if self.market_type == 'spot':
                if side == 'buy':
                    # 买入需要检查USDT余额
                    required_amount = amount * (price or self.get_latest_price() or 0)
                    return self.account_manager.has_sufficient_balance(
                        self.exchange_name, 'spot', required_amount, 'usdt'
                    )
                else:
                    # 卖出需要检查基础币种余额
                    base_currency = self.symbol.split('-')[0]
                    return self.account_manager.has_sufficient_balance(
                        self.exchange_name, 'spot', amount, base_currency
                    )
            else:
                # 合约交易检查保证金
                return self.account_manager.has_sufficient_balance(
                    self.exchange_name, 'futures', amount * 0.1  # 假设10倍杠杆
                )
                
        except Exception as e:
            self.logger.error(f"检查余额失败: {e}")
            return False
    
    def _record_initial_balance(self) -> None:
        """记录初始余额"""
        try:
            balance = self.account_manager.get_total_balance()
            
            self.stats['start_balance'] = balance
            self.stats['current_balance'] = balance
            
        except Exception as e:
            self.logger.error(f"记录初始余额失败: {e}")
    
    def _cancel_all_active_orders(self) -> None:
        """取消所有活跃订单"""
        try:
            active_orders = self.order_manager.get_orders_by_strategy(self.strategy_name)
            active_orders = [order for order in active_orders 
                           if order['status'] in ['created', 'submitted', 'partial_filled']]
            
            for order in active_orders:
                self.cancel_order(order['order_id'])
                
        except Exception as e:
            self.logger.error(f"取消活跃订单失败: {e}")
    
    def _update_final_stats(self) -> None:
        """更新最终统计"""
        try:
            # 更新当前余额
            if self.market_type == 'spot':
                balance = self.account_manager.get_total_balance(
                    self.exchange_name, 'spot', 'usdt'
                )
            else:
                balance = self.account_manager.get_total_balance(
                    self.exchange_name, 'futures'
                )
            
            self.stats['current_balance'] = balance
            self.stats['total_profit'] = balance - self.stats['start_balance']
            
            # 统计订单信息
            strategy_orders = self.order_manager.get_orders_by_strategy(self.strategy_name)
            filled_orders = [order for order in strategy_orders if order['status'] == 'filled']
            self.stats['filled_orders'] = len(filled_orders)
            
            # 计算胜率
            if self.stats['win_count'] + self.stats['loss_count'] > 0:
                win_rate = self.stats['win_count'] / (self.stats['win_count'] + self.stats['loss_count'])
                self.stats['win_rate'] = win_rate
            
            self.logger.info(f"策略统计: {self.stats}")
            
        except Exception as e:
            self.logger.error(f"更新最终统计失败: {e}")
    
    def get_stats(self) -> Dict[str, Any]:
        """
        获取策略统计信息
        
        Returns:
            统计信息
        """
        stats = self.stats.copy()
        stats.update({
            'strategy_name': self.strategy_name,
            'symbol': self.symbol,
            'exchange': self.exchange_name,
            'market_type': self.market_type,
            'running': self.running,
            'paused': self.paused,
            'start_time': self.start_time,
            'last_update_time': self.last_update_time,
            'run_duration': int(time.time()) - self.start_time if self.start_time > 0 else 0
        })
        
        return stats
    
    def update_last_time(self) -> None:
        """更新最后更新时间"""
        self.last_update_time = int(time.time())
    
    def _save_strategy_start_info(self) -> None:
        """保存策略启动信息"""
        try:
            strategy_data = {
                'name': self.strategy_name,
                'type': self.__class__.__name__.lower().replace('strategy', ''),
                'symbol': self.symbol,
                'exchange': self.exchange_name,
                'market_type': self.market_type,
                'config': self.config,
                'status': 'running',
                'created_at': time.time(),
                'updated_at': time.time()
            }
            
            self.persistence.save_strategy(strategy_data)
            
        except Exception as e:
            self.logger.error(f"保存策略启动信息失败: {e}")
    
    def _save_strategy_stop_info(self) -> None:
        """保存策略停止信息"""
        try:
            strategy_data = {
                'name': self.strategy_name,
                'status': 'stopped',
                'updated_at': time.time()
            }
            
            self.persistence.save_strategy(strategy_data)
            
            # 保存最终性能数据
            self._save_performance_data()
            
        except Exception as e:
            self.logger.error(f"保存策略停止信息失败: {e}")
    
    def _save_order_info(self, order: Dict[str, Any], exchange_result: Dict[str, Any]) -> None:
        """保存订单信息"""
        try:
            order_data = {
                'id': order['order_id'],
                'strategy': self.strategy_name,
                'exchange_order_id': exchange_result.get('order_id'),
                'symbol': self.symbol,
                'side': order['side'],
                'type': order['order_type'],
                'amount': order['amount'],
                'price': order.get('price'),
                'filled_amount': 0.0,
                'filled_price': 0.0,
                'status': 'submitted',
                'fee': 0.0,
                'fee_currency': '',
                'grid_level': order.get('grid_level'),
                'created_at': time.time(),
                'updated_at': time.time()
            }
            
            self.persistence.save_order(order_data)
            
        except Exception as e:
            self.logger.error(f"保存订单信息失败: {e}")
    
    def _save_trade_info(self, trade_data: Dict[str, Any]) -> None:
        """保存交易信息"""
        try:
            trade_info = {
                'order_id': trade_data.get('order_id'),
                'strategy': self.strategy_name,
                'exchange_trade_id': trade_data.get('trade_id'),
                'symbol': self.symbol,
                'side': trade_data.get('side'),
                'amount': trade_data.get('amount', 0.0),
                'price': trade_data.get('price', 0.0),
                'fee': trade_data.get('fee', 0.0),
                'fee_currency': trade_data.get('fee_currency', ''),
                'profit_loss': trade_data.get('profit_loss', 0.0),
                'executed_at': trade_data.get('timestamp', time.time())
            }
            
            self.persistence.save_trade(trade_info)
            
        except Exception as e:
            self.logger.error(f"保存交易信息失败: {e}")
    
    def _save_performance_data(self) -> None:
        """保存性能数据"""
        try:
            from datetime import datetime, date
            
            stats = self.get_stats()
            
            performance_data = {
                'strategy_name': self.strategy_name,
                'date': date.today(),
                'total_return': (stats['current_balance'] - stats['start_balance']) / stats['start_balance'] if stats['start_balance'] > 0 else 0.0,
                'daily_return': 0.0,  # 需要根据实际情况计算
                'cumulative_return': (stats['current_balance'] - stats['start_balance']) / stats['start_balance'] if stats['start_balance'] > 0 else 0.0,
                'max_drawdown': stats.get('max_drawdown', 0.0),
                'volatility': 0.0,  # 需要根据价格波动计算
                'sharpe_ratio': 0.0,  # 需要根据收益和风险计算
                'total_trades': stats.get('filled_orders', 0),
                'winning_trades': stats.get('win_count', 0),
                'losing_trades': stats.get('loss_count', 0),
                'win_rate': stats.get('win_rate', 0.0),
                'initial_balance': stats['start_balance'],
                'current_balance': stats['current_balance'],
                'total_profit': stats.get('total_profit', 0.0),
                'total_loss': 0.0,  # 需要根据实际亏损计算
                'created_at': time.time()
            }
            
            self.persistence.save_performance(performance_data)
            
        except Exception as e:
            self.logger.error(f"保存性能数据失败: {e}")
    
    def save_alert(self, level: str, title: str, message: str) -> None:
        """
        保存告警信息
        
        Args:
            level: 告警级别 (info/warning/error/critical)
            title: 告警标题
            message: 告警消息
        """
        try:
            alert_data = {
                'level': level,
                'title': title,
                'message': message,
                'source': 'strategy',
                'strategy_name': self.strategy_name,
                'status': 'active',
                'created_at': time.time()
            }
            
            self.persistence.save_alert(alert_data)
            
        except Exception as e:
            self.logger.error(f"保存告警信息失败: {e}")